-
Notifications
You must be signed in to change notification settings - Fork 91
🔧 fix: use getFlattenedRoutes() to include guard() schemas #300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
🔧 fix: use getFlattenedRoutes() to include guard() schemas #300
Conversation
… spec Fixes guard() schemas not appearing in generated OpenAPI documentation. Changes: - Replace app.getGlobalRoutes() with app.getFlattenedRoutes?.() ?? app.getGlobalRoutes() - Maintains backward compatibility with older Elysia versions This allows the OpenAPI plugin to access guard() schemas that are now exposed via Elysia's getFlattenedRoutes() method. Requires: elysiajs/elysia#1533
WalkthroughAdds schema-flattening helpers and a route-flattening mechanism to merge guard() schemas (body, query, headers, params, cookie, responses) into route hook properties, and updates OpenAPI generation to use flattened routes before producing the final OpenAPI document. Changes
Sequence Diagram(s)sequenceDiagram
participant App as ElysiaApp
participant OpenAPI as toOpenAPISchema
participant Flat as flattenRoutes
participant Route as RouteItem
note over App,Flat: New flattening step merges guard() schemas into routes
App->>Flat: getGlobalRoutes() / input routes
Flat-->>OpenAPI: flattened routes (merged body/query/headers/params/cookie/responses)
OpenAPI->>OpenAPI: normalize references, convert string refs -> TypeBox refs
OpenAPI->>Caller: final OpenAPI JSON
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/openapi.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/openapi.ts (2)
example/gen.ts (1)
app(6-77)test/gen/sample.ts (1)
app(5-61)
fix: use @ts-expect-error instead of @ts-ignore Addresses coderabbitai feedback on PR elysiajs#300. Changed from @ts-ignore to @ts-expect-error for better type safety. This ensures the suppression is still necessary - if the error goes away in the future (e.g., after types are updated), @ts-expect-error will fail the build, alerting us to remove it. Also improved the comment to be more descriptive about why the suppression is needed.
Addresses coderabbitai feedback on PR elysiajs#300. Changed from @ts-ignore to @ts-expect-error for better type safety. This ensures the suppression is still necessary - if the error goes away in the future (e.g., after types are updated), @ts-expect-error will fail the build, alerting us to remove it. Also improved the comment to be more descriptive about why the suppression is needed.
1fcdb20 to
da02e4d
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
1 similar comment
✅ Actions performedReview triggered.
|
- Add flattenRoutes() and schema merging helpers to elysia-openapi - Replace app.getFlattenedRoutes() call with local implementation - Use app.getGlobalRoutes() and flatten routes internally - Enables guard() schemas to appear in OpenAPI documentation - Allows future support for external schema conversions (z.toJSONSchema, etc.) This moves the flattening logic from elysia core to the OpenAPI plugin where it belongs, as suggested by the maintainer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/openapi.ts (2)
266-330: Response merging works for TypeBox/status maps but may misclassify~standardschemasThe
mergeResponseSchema+isTSchemacombo correctly handles the common cases (TypeBox schema vs{ 401: ... }status maps, including your new guard-response test). However, any non-TypeBox object (including~standardvendor schemas such as Zod/Valibot) is currently treated as “not a schema” and funneled through the same path as status-code maps.That means scenarios like:
- route-level
response: t.Object(...)(TypeBox),- guard-level
response: someZodSchema(non-status,~standard),will be merged as if the guard schema were a status-map container, which is likely not what you want and can produce awkward shapes that later go through the single-schema response branch.
Consider tightening the detection so that “plain schemas” include both TypeBox (
Kind in value) and~standardshapes, and only treat objects without either as status maps. That keeps your current behavior for{ 401: ... }but avoids misclassifying standalone non-TypeBox schemas. A small regression test forguard({ response: someZodSchema }, ...)would make this explicit.
335-434: Route flattening for guards looks good; consider clarifying reliance on local vs core flatteningThe
mergeStandaloneValidators+flattenRoutes(app.getGlobalRoutes())approach is a clean way to surfaceguard()schemas to the existing OpenAPI generation logic, and keeping this as a pure transform (cloning the route object whenstandaloneValidatoris present) avoids mutatingapp.routes.One thing to double‑check is alignment with expectations/documentation: the PR description still talks about calling
app.getFlattenedRoutes?.() ?? app.getGlobalRoutes(), but the implementation now always usesgetGlobalRoutes()and does its own flattening. That’s fine from a compatibility standpoint, but it would be good either to:
- update the PR/docs to match this behavior, or
- optionally prefer
app.getFlattenedRoutes?.()when available and fall back toflattenRoutes(getGlobalRoutes()), to reduce drift from core semantics.Functionally the current code is sound; this is mostly about keeping intent and implementation in sync.
Also applies to: 626-628
test/guard-schema.test.ts (1)
1-88: Nice focused regression coverage for guard headers and responsesThese tests exercise the key failure modes that motivated the change (guard headers missing from parameters and guard responses not merged with route-level 200s) by going through the real
/openapi/jsonendpoint. This is a solid baseline. If you later extend coverage, adding cases for guard-driven query/params/cookie schemas or nested guards would broaden confidence, but not required for this fix.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/openapi.ts(3 hunks)test/guard-schema.test.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
test/guard-schema.test.ts (1)
src/index.ts (1)
openapi(40-181)
Problem
Guard schemas defined via
guard()do not appear in the generated OpenAPI specification. Routes exist but lackrequestBodyand parameter schemas.Current Behavior
OpenAPI output:
{ "/sign-up": { "post": { "operationId": "postSign-up" // No requestBody! } } }Root Cause
The plugin reads routes via
app.getGlobalRoutes(), which returns guard schemas instandaloneValidatorarrays. The plugin only checks direct schema properties likeroute.hooks.body.Solution
Implement local schema flattening directly in elysia-openapi. This approach:
standaloneValidatorarrays into direct hook propertiesImplementation
Added helper functions to
src/openapi.ts:flattenRoutes()- Main function that flattens guard schemasmergeStandaloneValidators()- Merges standaloneValidator arraysmergeSchemaProperty()- Merges body/query/headers/params/cookie schemasmergeResponseSchema()- Handles response schemas and status code objectsisTSchema()- Distinguishes TypeBox schemas from status code objects using Kind symbolnormalizeSchemaReference()- Converts string references to TRef nodesmergeObjectSchemas()- Merges TypeBox object schemasFile:
src/openapi.ts, line ~628Why Local Implementation?
Per @SaltyAom feedback, implementing schema flattening in elysia-openapi (rather than elysia core) allows:
mapJsonSchemaAfter Fix
OpenAPI output:
{ "/sign-up": { "post": { "requestBody": { "content": { "application/json": { "schema": { "type": "object", "properties": { "username": { "type": "string" }, "password": { "type": "string" } }, "required": ["username", "password"] } } }, "required": true }, "operationId": "postSign-up" } } }Testing
✅ Added comprehensive tests in
test/guard-schema.test.ts:The fix has been tested with:
.model()All schemas now appear correctly in the OpenAPI documentation.